home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog 125
/
Freelog_MarsAvril2015_No125.iso
/
ViePratique
/
ArchiFacile
/
ArchiFacileSetup.exe
/
{app}
/
nw.pak
/
Unnamed File 000123.txt
< prev
next >
Wrap
Text File
|
2014-10-14
|
8KB
|
250 lines
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('cr.ui', function() {
/**
* Constructor for FocusManager singleton. Checks focus of elements to ensure
* that elements in "background" pages (i.e., those in a dialog that is not
* the topmost overlay) do not receive focus.
* @constructor
*/
function FocusManager() {
}
FocusManager.prototype = {
/**
* Whether focus is being transferred backward or forward through the DOM.
* @type {boolean}
* @private
*/
focusDirBackwards_: false,
/**
* Determines whether the |child| is a descendant of |parent| in the page's
* DOM.
* @param {Element} parent The parent element to test.
* @param {Element} child The child element to test.
* @return {boolean} True if |child| is a descendant of |parent|.
* @private
*/
isDescendantOf_: function(parent, child) {
var current = child;
while (current) {
current = current.parentNode;
if (typeof(current) == 'undefined' ||
typeof(current) == 'null' ||
current === document.body) {
return false;
} else if (current === parent) {
return true;
}
}
return false;
},
/**
* Returns the parent element containing all elements which should be
* allowed to receive focus.
* @return {Element} The element containing focusable elements.
*/
getFocusParent: function() {
return document.body;
},
/**
* Returns the elements on the page capable of receiving focus.
* @return {Array.Element} The focusable elements.
*/
getFocusableElements_: function() {
var focusableDiv = this.getFocusParent();
// Create a TreeWalker object to traverse the DOM from |focusableDiv|.
var treeWalker = document.createTreeWalker(
focusableDiv,
NodeFilter.SHOW_ELEMENT,
{ acceptNode: function(node) {
var style = window.getComputedStyle(node);
// Reject all hidden nodes. FILTER_REJECT also rejects these
// nodes' children, so non-hidden elements that are descendants of
// hidden <div>s will correctly be rejected.
if (node.hidden || style.display == 'none' ||
style.visibility == 'hidden') {
return NodeFilter.FILTER_REJECT;
}
// Skip nodes that cannot receive focus. FILTER_SKIP does not
// cause this node's children also to be skipped.
if (node.disabled || node.tabIndex < 0)
return NodeFilter.FILTER_SKIP;
// Accept nodes that are non-hidden and focusable.
return NodeFilter.FILTER_ACCEPT;
}
},
false);
var focusable = [];
while (treeWalker.nextNode())
focusable.push(treeWalker.currentNode);
return focusable;
},
/**
* Dispatches an 'elementFocused' event to notify an element that it has
* received focus. When focus wraps around within the a page, only the
* element that has focus after the wrapping receives an 'elementFocused'
* event. This differs from the native 'focus' event which is received by
* an element outside the page first, followed by a 'focus' on an element
* within the page after the FocusManager has intervened.
* @param {Element} element The element that has received focus.
* @private
*/
dispatchFocusEvent_: function(element) {
cr.dispatchSimpleEvent(element, 'elementFocused', true, false);
},
/**
* Attempts to focus the appropriate element in the current dialog.
* @private
*/
setFocus_: function() {
var element = this.selectFocusableElement_();
if (element) {
element.focus();
this.dispatchFocusEvent_(element);
}
},
/**
* Attempts to focus the first element in the current dialog.
*/
focusFirstElement: function() {
this.focusFirstElement_();
},
/**
* Selects first appropriate focusable element according to the
* current focus direction and element type. If it is a radio button,
* checked one is selected from the group.
* @private
*/
selectFocusableElement_: function() {
// If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab"
// and has caused the focus to be transferred backward, outside of the
// current dialog. In this case, loop around and try to focus the last
// element of the dialog; otherwise, try to focus the first element of the
// dialog.
var focusableElements = this.getFocusableElements_();
var element = this.focusDirBackwards_ ? focusableElements.pop() :
focusableElements.shift();
if (!element)
return null;
if (element.tagName != 'INPUT' || element.type != 'radio' ||
element.name == '') {
return element;
}
if (!element.checked) {
for (var i = 0; i < focusableElements.length; i++) {
var e = focusableElements[i];
if (e && e.tagName == 'INPUT' && e.type == 'radio' &&
e.name == element.name && e.checked) {
element = e;
break;
}
}
}
return element;
},
/**
* Handler for focus events on the page.
* @param {Event} event The focus event.
* @private
*/
onDocumentFocus_: function(event) {
// If the element being focused is a descendant of the currently visible
// page, focus is valid.
if (this.isDescendantOf_(this.getFocusParent(), event.target)) {
this.dispatchFocusEvent_(event.target);
return;
}
// Focus event handlers for descendant elements might dispatch another
// focus event.
event.stopPropagation();
// The target of the focus event is not in the topmost visible page and
// should not be focused.
event.target.blur();
// Attempt to wrap around focus within the current page.
this.setFocus_();
},
/**
* Handler for keydown events on the page.
* @param {Event} event The keydown event.
* @private
*/
onDocumentKeyDown_: function(event) {
/** @const */ var tabKeyCode = 9;
if (event.keyCode == tabKeyCode) {
// If the "Shift" key is held, focus is being transferred backward in
// the page.
this.focusDirBackwards_ = event.shiftKey ? true : false;
}
},
/**
* Initializes the FocusManager by listening for events in the document.
*/
initialize: function() {
document.addEventListener('focus', this.onDocumentFocus_.bind(this),
true);
document.addEventListener('keydown', this.onDocumentKeyDown_.bind(this),
true);
},
};
/**
* Disable mouse-focus for button controls.
* Button form controls are mouse-focusable since Chromium 30. We want the
* old behavior in some WebUI pages.
*/
FocusManager.disableMouseFocusOnButtons = function() {
document.addEventListener('mousedown', function(event) {
if (event.defaultPrevented)
return;
var node = event.target;
var tagName = node.tagName;
if (tagName != 'BUTTON' && tagName != 'INPUT') {
do {
node = node.parentNode;
if (!node || node.nodeType != Node.ELEMENT_NODE)
return;
} while (node.tagName != 'BUTTON');
}
var type = node.type;
if (type == 'button' || type == 'reset' || type == 'submit' ||
type == 'radio' || type == 'checkbox') {
if (document.activeElement != node)
document.activeElement.blur();
// Focus the current window so that if the active element is in another
// window, it is deactivated.
window.focus();
event.preventDefault();
}
}, false);
};
return {
FocusManager: FocusManager,
};
});